home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Development Tools & Languages / Macintosh Common Lisp Related / User Contributions / zebu v3.3.3 (LALR parser) / zebu-tree-attributes.lisp < prev   
Encoding:
Text File  |  1994-09-12  |  27.5 KB  |  791 lines  |  [TEXT/ttxt]

  1. ; -*- mode:     CL -*- ----------------------------------------------------- ;
  2. ; File:         zebu-tree-attributes.l
  3. ; Description:  Functions operating on abstract syntax trees
  4. ; Author:       Joachim H. Laubsch
  5. ; Created:      26-Feb-93
  6. ; Modified:     Tue Aug  2 17:11:32 1994 (Joachim H. Laubsch)
  7. ; Language:     CL
  8. ; Package:      ZEBU
  9. ; Status:       Experimental (Do Not Distribute) 
  10. ; RCS $Header: $
  11. ;
  12. ; (c) Copyright 1990, Hewlett-Packard Company
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16. (in-package "ZEBU")
  17. (require "zebu-kb-domain")
  18. (provide "zebu-tree-attributes")
  19.  
  20. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  21. ;;                               tree attributes
  22. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  23. ;; Plist implementation
  24.  
  25. (declaim (inline KB-TREE-ATTRIBUTES))
  26. (defun KB-tree-attributes (class-name)
  27.   (get (the symbol class-name) 'KB-TREE-ATTRIBUTES))
  28. ;----------------------------------------------------------------------------;
  29. ; define-tree-attributes
  30. ;-----------------------
  31. ; for each class enter the tree attributes in the form:
  32. ; ((<reader1> <reader2> ...) .  (<writer1> <writer2> ...))
  33. ; where <readeri> is the name of the accessor for slot i
  34. ;       <writeri> is a compiled function to set slot i
  35.  
  36. (defun define-tree-attributes (class slots)
  37.   (let (writers)
  38.     (dolist (slot slots)
  39.       (let ((def `(lambda (x y)
  40.            (declare (type ,class x))
  41.            (setf (,slot x) y))))
  42.     (push
  43.      (compile nil def)
  44.            writers)))
  45.     (setf (get (the symbol class) 'KB-TREE-ATTRIBUTES)
  46.       (cons slots (nreverse writers))) ))
  47.  
  48. ;; The reason for this macro is that then the compiler does
  49. ;; not need to be loaded when a file is loaded which contains 
  50. ;; def-tree-attributes forms
  51. #||
  52. (defmacro def-tree-attributes (class &rest slots)
  53.   (check-type class symbol)
  54.   (let (writers setters)
  55.     (dolist (slot slots)
  56.       (check-type slot symbol)
  57.       (let* ((setter (intern (format nil "SET-~a" slot)))
  58.          (def `(defun ,setter (x y)
  59.             (declare (type ,class x))
  60.             (setf (,slot x) y))))
  61.     (push def writers)
  62.     (push setter setters)))
  63.     `(progn
  64.       ,@writers
  65.       (setf (get ',class 'KB-TREE-ATTRIBUTES)
  66.        (cons
  67.     ',slots
  68.     (mapcar #'(lambda (setter) (symbol-function setter))
  69.             ',(nreverse setters)))))))
  70. ||#
  71.  
  72. ;; avoid duplicate definitions
  73. (defmacro def-tree-attributes (class &rest slots)
  74.   (check-type class symbol)
  75.   (let (writers setters)
  76.     (dolist (slot slots)
  77.       (check-type slot symbol)
  78.       (let ((setter (intern (format nil "SET-~a" slot))))
  79.     (unless (fboundp setter)
  80.       (push `(defun ,setter (x y)
  81.           (declare (type ,class x))
  82.           (setf (,slot x) y))
  83.         writers))
  84.     (push setter setters)))
  85.     `(progn
  86.       (eval-when (compile eval) ,@writers)
  87.       (setf (get ',class 'KB-TREE-ATTRIBUTES)
  88.        (cons
  89.     ',slots
  90.     (mapcar #'(lambda (setter) (symbol-function setter))
  91.         ',(nreverse setters)))))))
  92.  
  93. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  94. ;; Hashtable implementation 
  95. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  96. #||
  97. (defvar *KB-TREE-ATTRIBUTES* (make-hash-table))
  98. (declaim (type HASH-TABLE *KB-TREE-ATTRIBUTES*))
  99.  
  100. (declaim (inline KB-TREE-ATTRIBUTES))
  101. (defun KB-TREE-ATTRIBUTES (class-name)
  102.   (gethash class-name *KB-TREE-ATTRIBUTES*))
  103.  
  104. ;----------------------------------------------------------------------------;
  105. ; define-tree-attributes
  106. ;-----------------------
  107. ; for each class enter the tree attributes in the form:
  108. ; ((<reader1> <reader2> ...) .  (<writer1> <writer2> ...))
  109. ; where <readeri> is the name of the accessor for slot i
  110. ;       <writeri> is a compiled function to set slot i
  111.  
  112. (declaim (inline KB-TREE-ATTRIBUTES))
  113. (defun define-tree-attributes (class slots)
  114.   (let (writers)
  115.     (dolist (slot slots)
  116.       (let ((def `(lambda (x y)
  117.            (declare (type ,class x))
  118.            (setf (,slot x) y))))
  119.     (push 
  120.      (compile nil def)
  121.      writers)))
  122.     (setf (gethash class *KB-TREE-ATTRIBUTES*)
  123.       (cons slots (nreverse writers))) ))
  124. ||#
  125.  
  126. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  127. ;;                              Set/Sequence Valued Slots
  128. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  129.  
  130. (defvar *KB-SLOT-types* (make-hash-table))
  131. (declaim (type HASH-TABLE *KB-SLOT-types*))
  132.  
  133. (declaim (inline KB-set-valued-slot-p))
  134. (defun KB-set-valued-slot-p (reader)
  135.   (eq (gethash reader *KB-SLOT-types*) ':set))
  136.  
  137. (defun KB-def-slot-type (reader type)
  138.   (setf (gethash reader *KB-SLOT-types*) type))
  139.  
  140.  
  141. ;----------------------------------------------------------------------------;
  142. ; kids
  143. ;-----
  144. ; collect all the kids of OBJECT which are in KB-Domain.
  145. ; if a kid is a SET or SEQUENCE of subnodes, include those which are
  146. ; in KB-Domain.
  147.  
  148. (defun kids (object &aux R)
  149.   (declare (inline KB-TREE-ATTRIBUTES))
  150.   (macrolet ((readers (x) `(the list (car (the cons ,x)))))
  151.     (let ((ta (KB-tree-attributes (type-of object))))
  152.       (when ta
  153.     (dolist (reader (readers ta) R)
  154.       (declare (symbol reader))
  155.       (let ((kids (funcall (the function (symbol-function reader)) object)))
  156.         (cond ((consp kids)
  157.            (dolist (k (the list kids))
  158.              (when (KB-Domain-p k) (push k R))))
  159.           ((KB-Domain-p kids)
  160.            (push kids R))))))))
  161.   )
  162.  
  163. ;-----------------------------------------------------------------------------;
  164. ; subexpressions
  165. ;---------------
  166. ; All immediate subexpressions of a KB-Domain-element
  167. ; anything not of type KB-Domain-element does not have components
  168.  
  169. (declaim (inline subexpressions))
  170. (defun subexpressions (KB-Domain-element)
  171.   (check-type KB-Domain-element KB-Domain)
  172.   (kids KB-Domain-element))
  173.  
  174. ;----------------------------------------------------------------------------;
  175. ; for-each-kid
  176. ;-------------
  177. ; iterate over all kids of NODE which are in KB-Domain, calling FUN.
  178. ; NODE must be of type KB-Domain.
  179. ; Returns nil
  180.  
  181. (defun for-each-kid (FUN NODE)
  182.   (declare (type function fun))
  183.   (macrolet ((readers (x) `(the list (car (the cons ,x)))))
  184.     (if (KB-Domain-p NODE)        ;  (subtypep typ 'KB-Domain)
  185.     (let ((ta (KB-tree-attributes (type-of node))))
  186.       (when ta
  187.         (dolist (reader (readers ta))
  188.           (declare (symbol reader))
  189.           (let ((subnode (funcall (the function (symbol-function reader)) NODE)))
  190.         (cond
  191.           ((CONSp subnode)    ; value is a set or sequence
  192.            (dolist (kid (the list subnode))
  193.              (when (KB-Domain-p kid) (funcall FUN kid))))
  194.           ((KB-Domain-p subnode) (funcall fun subnode)))))))
  195.       (error "Can't iterate over non KB-Domain object: ~S" NODE))))
  196.  
  197. (defun for-each-kid! (FUN NODE)
  198.   ;; just like for-each-kid, but if FUN(kid) ~eq kid then replace kid
  199.   ;; by the value of FUN(kid)
  200.   ;; returns NODE
  201.   (declare (type function fun))
  202.   (declare (inline KB-TREE-ATTRIBUTES))
  203.   (if (KB-Domain-p NODE)        ;  (subtypep typ 'KB-Domain)
  204.       (macrolet ((readers (x) `(the list (car (the cons ,x))))
  205.          (writers (x) `(the list (cdr (the cons ,x)))))
  206.     (let ((ta (KB-tree-attributes (type-of node))))
  207.       (if (null ta)
  208.           NODE
  209.         ;; ta ((<reader1> <reader2> ...) (<writer1> <writer2> ...))
  210.         (do ((r (readers ta) (cdr r)) (w (writers ta) (cdr w)))
  211.         ((null r) NODE)
  212.           (let* ((reader (car (the cons r)))
  213.              (subnode (funcall (the function (symbol-function reader))
  214.                        NODE)))
  215.         (cond
  216.           ((CONSp subnode)    ; value is a set or sequence
  217.            (do ((kids (the list subnode) (cdr kids)))
  218.                ((null kids))
  219.              (let ((kid (car (the cons kids))))
  220.                (if (KB-Domain-p kid)
  221.                (let ((newval (funcall FUN kid)))
  222.                  (unless (eq kid newval)
  223.                    (setf (car kids) newval)))))))
  224.           ((KB-Domain-p subnode)
  225.            (let ((vv (funcall fun subnode)))
  226.              (unless (eq vv subnode)
  227.                ;; (eval `(setf (,reader ,NODE) ',vv))
  228.                (funcall (the compiled-function (car w)) NODE vv))))))))))
  229.     (error "Can't iterate over non KB-Domain object: ~S" NODE)))
  230.  
  231. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  232. ;;                             preorder-transform
  233. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  234. #||
  235. (defun preorder-transform (node funs)
  236.   (check-type node KB-Domain)
  237.   (check-type funs list)
  238.   (macrolet ((readers (x) `(the list (car (the cons ,x))))
  239.          (writers (x) `(the list (cdr (the cons ,x))))
  240.          (mung-node (n) `(preorder-transform-aux (transform-node ,n))))
  241.     (labels ((preorder-transform-aux (n)
  242.            (let ((ta (KB-tree-attributes (type-of n))))
  243.          (when (null ta)
  244.            (return-from preorder-transform-aux n))
  245.          (do ((r (readers ta) (cdr r)) (w (writers ta) (cdr w)))
  246.              ((null r) n)
  247.            (let* ((reader (car (the cons r)))
  248.               (subnode (funcall (the function (symbol-function reader))
  249.                         n)))
  250.              (cond ((CONSp subnode) ; value is a set or sequence
  251.                 (do ((kids (the list subnode) (cdr kids)))
  252.                 ((null kids))
  253.                   (let ((kid (car (the cons kids))))
  254.                 (when (KB-Domain-p kid)
  255.                   (let ((newval (mung-node kid)))
  256.                     (unless (eq kid newval)
  257.                       (setf (car (the cons kids)) newval)))))))
  258.                ((KB-Domain-p subnode)
  259.                 (let ((subnode1 (mung-node subnode)))
  260.                   (unless (eq subnode1 subnode)
  261.                 (funcall (car (the cons w)) n subnode1)))))))))
  262.          (transform-node (n)
  263.            (let (fun-fired?)
  264.          (do ((funRest (the list funs))
  265.               (oldn (KB-copy n) (KB-copy n))
  266.               )
  267.              ((null funRest) n)
  268.            (let ((fun (car funRest)))
  269.              ;; run each function to acquiescence
  270.              ;; each function returns 2 values, 
  271.              ;; (1) the new node
  272.              ;; (2) whether there was a change in this node
  273.              ;;     that may make it necessary for this function to run
  274.              ;;     again on the same node
  275.              ;; if a function had an effect --- fun-fired? = T  ---
  276.              ;; we start all over with all functions (except the current)
  277.              (loop do (multiple-value-bind (v change?)
  278.                   (funcall (the Function fun) n)
  279.                 (if change?
  280.                     (setq n v)
  281.                   (if (eq n v)
  282.                       (return n)
  283.                     (setq n v)))
  284.                 (format t "~%;; ~S~%;; ~S~%;; --> ~S" fun oldn v)
  285.                 (setq fun-fired? t)))
  286.              (if fun-fired?
  287.              (setq funRest (remove fun funs)
  288.                    fun-fired? nil)
  289.                (pop funRest)))))))
  290.       (mung-node node))))
  291. ||#
  292. (defun preorder-transform (node funs)
  293.   (declare (inline KB-TREE-ATTRIBUTES))
  294.   (check-type node KB-Domain) (check-type funs list)
  295.   (macrolet ((readers (x) `(the list (car (the cons ,x))))
  296.          (writers (x) `(the list (cdr (the cons ,x))))
  297.          (mung-node (n) `(preorder-transform-aux (transform-node ,n))))
  298.     (flet ((transform-node (n)
  299.          (let (fun-fired?)
  300.            (do ((funRest (the list funs)))
  301.            ((null funRest) n)
  302.          (let ((fun (car funRest)))
  303.            ;; run each function to acquiescence
  304.            ;; each function returns 2 values, 
  305.            ;; (1) the new node
  306.            ;; (2) whether there was a change in this node
  307.            ;;     that may make it necessary for this function to run
  308.            ;;     again on the same node
  309.            ;; if a function had an effect --- fun-fired? = T  ---
  310.            ;; we start all over with all functions (except the current)
  311.            (loop (multiple-value-bind (v change?)
  312.                  (funcall (the Function fun) n)
  313.                (if change?
  314.                    (setq n v)
  315.                  (if (eq n v)
  316.                  (return n)
  317.                    (setq n v)))
  318.                ;; (format t "~%;; ~S~%;; ~S~%;; --> ~S" fun oldn v)
  319.                (setq fun-fired? t)))
  320.            (if fun-fired?
  321.                (setq funRest (remove fun funs)
  322.                  fun-fired? nil)
  323.              (pop funRest)))))))
  324.       (labels ((preorder-transform-aux (n)
  325.          (let ((ta (KB-tree-attributes (type-of n))))
  326.            (when (null ta)
  327.              (return-from preorder-transform-aux n))
  328.            (do ((r (readers ta) (cdr r)) (w (writers ta) (cdr w)))
  329.                ((null r) n)
  330.              (let* ((reader (car (the cons r)))
  331.                 (subnode (funcall (the function
  332.                            (symbol-function reader))
  333.                           n)))
  334.                (cond ((CONSp subnode) ; value is a set or sequence
  335.                   (do ((kids (the list subnode) (cdr kids)))
  336.                   ((null kids))
  337.                 (let ((kid (car (the cons kids))))
  338.                   (when (KB-Domain-p kid)
  339.                     (let ((newval (mung-node kid)))
  340.                       (unless (eq kid newval)
  341.                     (setf (car (the cons kids)) newval)))))))
  342.                  ((KB-Domain-p subnode)
  343.                   (let ((subnode1 (mung-node subnode)))
  344.                 (unless (eq subnode1 subnode)
  345.                   (funcall (car (the cons w)) n subnode1))))))))))
  346.     (mung-node node)))))
  347.  
  348. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  349. ;;                             postorder-transform
  350. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  351. ;; just like preorder, but descend down first to the leaves, and then
  352. ;; transform from bottom-up
  353. (defun postorder-transform (node funs &optional (exhaustive nil))
  354.   (declare (inline KB-TREE-ATTRIBUTES))
  355.   (check-type node KB-Domain) (check-type funs list)
  356.   (macrolet ((readers (x) `(the list (car (the cons ,x))))
  357.          (writers (x) `(the list (cdr (the cons ,x))))
  358.          ;; here is the difference to preorder: recurse first!
  359.          (mung-node (n)
  360.            `(transform-node (postorder-transform-aux ,n))))
  361.     (flet ((transform-node (n)
  362.          ;; (format t "~%transform-node: ~S" n)
  363.          (do ((funRest (the list funs)) rule-fired?)
  364.          ((null funRest) n)
  365.            (let ((fun (car funRest)))
  366.          ;; run each function to acquiescence
  367.          ;; each function returns 2 values, 
  368.          ;; (1) the new node
  369.          ;; (2) whether there was a change in this node
  370.          ;;     that may make it necessary for this function to run
  371.          ;;     again on the same node
  372.          ;; if a function had an effect --- fun-fired? = T  ---
  373.          ;; we start all over at the leaves
  374.          (loop (multiple-value-bind (v change?)
  375.                (funcall (the Function fun) n)
  376.              (if change?
  377.                  (setq n v)
  378.                (if (eq n v)
  379.                    (return nil)
  380.                  (setq n v)))
  381.              (if exhaustive
  382.                  (return-from transform-node
  383.                    (values n t))
  384.                (setq rule-fired? t))))
  385.          (if rule-fired?
  386.              (setq funRest (remove fun funs)
  387.                rule-fired? nil)
  388.            (pop funRest)))))) 
  389.       (labels ((postorder-transform-aux (n)
  390.          (let ((ta (KB-tree-attributes (type-of n))))
  391.            (when (null ta)
  392.              (return-from postorder-transform-aux n))
  393.            ; (format t "~%postorder-transform: ~S" n)
  394.            (do ((r (readers ta) (cdr r)) (w (writers ta) (cdr w)))
  395.                ((null r) n)
  396.              (let* ((reader (car (the cons r)))
  397.                 (subnode (funcall (the function
  398.                            (symbol-function reader))
  399.                           n)))
  400.                (cond ((CONSp subnode) ; value is a set or sequence
  401.                   (do ((kids (the list subnode) (cdr kids)))
  402.                   ((null kids))
  403.                 (let ((kid (car (the cons kids))))
  404.                   (when (KB-Domain-p kid)
  405.                     (loop
  406.                      (multiple-value-bind (newval rule-fired?)
  407.                      (mung-node kid)
  408.                        (if (eq kid newval)
  409.                        (if rule-fired?
  410.                            (if exhaustive
  411.                            nil  ; go on
  412.                          (return nil))
  413.                          (return nil))
  414.                      (progn
  415.                        (setf (car (the cons kids)) newval)
  416.                        (setf kid newval)
  417.                        (if exhaustive
  418.                            nil     ; go on
  419.                          (return nil))))))))))
  420.                  ((KB-Domain-p subnode)
  421.                   (loop
  422.                    (multiple-value-bind (subnode1 rule-fired?)
  423.                    (mung-node subnode)
  424.                  (if (eq subnode1 subnode)
  425.                      (if rule-fired?
  426.                      (if exhaustive
  427.                          nil ; go on
  428.                        (return nil))
  429.                        (return nil))
  430.                    (progn
  431.                      (funcall (car (the cons w)) n subnode1)
  432.                      (setf subnode subnode1)
  433.                      (if exhaustive
  434.                      nil ; go on
  435.                        (return nil)))))))))))))
  436.     (loop (multiple-value-bind (new rule-fired?)
  437.           (mung-node node)
  438.         (if exhaustive
  439.             (if (or rule-fired? (not (eq new node)))
  440.             (setq node new)
  441.               (return new))
  442.           (return new))))))))
  443.  
  444. #||
  445. (defun descendants (object)
  446.   (let ((R (list object)))
  447.     (dolist (kid (kids object) R)
  448.       (nconc R (descendants kid)))))
  449. ||#
  450. ;; more efficiently:
  451.  
  452. ;----------------------------------------------------------------------------;
  453. ; descendants
  454. ;------------
  455.  
  456. (defun descendants (object &aux R)
  457.   (declare (inline KB-TREE-ATTRIBUTES))
  458.   (check-type object KB-Domain)    
  459.   (macrolet ((readers (x) `(the list (car (the cons ,x)))))  
  460.     (labels ((descendants-aux (object)
  461.            (let ((ta (KB-tree-attributes (type-of object))))
  462.          (when ta
  463.            (dolist (reader (readers ta))
  464.              (declare (symbol reader))
  465.              (let ((kids (funcall (the function (symbol-function reader))
  466.                       object)))
  467.                (cond ((consp kids)
  468.                   (dolist (k (the list kids))
  469.                 (push k R)
  470.                 (descendants-aux k)))
  471.                  ((KB-Domain-p kids)
  472.                   (push kids R)
  473.                   (descendants-aux kids)))))))))
  474.       (descendants-aux object)
  475.       (nreverse (cons object R)))))
  476.  
  477. ;----------------------------------------------------------------------------;
  478. ; for-each-descendant
  479. ;--------------------
  480. ; like for-each-kid
  481. ; Returns nil
  482.  
  483. (defun for-each-descendant (fn object)
  484.   (declare (type function fn))
  485.   (check-type object KB-Domain) 
  486.   (macrolet ((readers (x) `(the list (car (the cons ,x)))))  
  487.     (labels ((descendants-aux (object)
  488.            (let ((ta (KB-tree-attributes (type-of object))))
  489.          (when ta
  490.            (dolist (reader (readers ta))
  491.              (declare (symbol reader))
  492.              (let ((kids (funcall (the function (symbol-function reader))
  493.                       object)))
  494.                (cond ((consp kids)
  495.                   (dolist (k (the list kids))
  496.                 (funcall fn k)
  497.                 (descendants-aux k)))
  498.                  ((KB-Domain-p kids)
  499.                   (funcall fn kids)
  500.                   (descendants-aux kids)))))))))
  501.       (funcall fn object)
  502.       (descendants-aux object))))
  503.  
  504. ;----------------------------------------------------------------------------;
  505. ; KB-copy
  506. ;--------
  507. ; A copy function that walks down all the tree-attributes and copies
  508. ; unless called with :recursive-p Nil
  509.  
  510. #+LUCID
  511. (defmacro %copy-structure (x)
  512.     `(SYSTEM:copy-structure ,x))
  513.  
  514. #-LUCID
  515. (defun %copy-structure (term)
  516.   (let* ((ttype (type-of term))
  517.      (copy-fn (find-symbol (concatenate 
  518.                 'string "COPY-" (symbol-name ttype))
  519.                    (symbol-package ttype))))
  520.     (if (fboundp copy-fn)
  521.     (funcall copy-fn term)
  522.       (error "No COPY function defined for ~s:~a" term ttype)))) 
  523.  
  524. (defun KB-copy (term &optional (recursive-p t))
  525.   (declare (inline KB-TREE-ATTRIBUTES))
  526.   (macrolet ((readers (x) `(the list (car (the cons ,x))))
  527.          (writers (x) `(the list (cdr (the cons ,x)))))
  528.     (labels ((KB-copy-aux (term)
  529.            (declare (type KB-Domain term))
  530.            (let ((new-term (%COPY-STRUCTURE term))
  531.              (ta (KB-tree-attributes (type-of term))))
  532.          (if (null ta)
  533.              new-term
  534.            (do ((r (readers ta) (cdr r)) (w (writers ta) (cdr w)))
  535.                ((null r) new-term)
  536.              (let* ((reader (car (the cons r)))
  537.                 (writer (car (the cons w)))
  538.                 (subnode (funcall (the function
  539.                            (symbol-function
  540.                             (the symbol reader)))
  541.                           new-term)))
  542.                (cond ((CONSp subnode) ; value is a set or sequence 
  543.                   (let ((newsubnode
  544.                      (copy-list (the list subnode))))
  545.                 (funcall (the compiled-function writer)
  546.                      new-term newsubnode)
  547.                 (do ((nrest newsubnode (cdr nrest)))
  548.                     ((null nrest))
  549.                   (let ((kid (car (the cons nrest))))
  550.                     (when (KB-Domain-p kid)
  551.                       (setf (car (the cons nrest))
  552.                         (KB-copy-aux kid)))))))
  553.                  ((KB-Domain-p subnode)
  554.                   (funcall (the compiled-function writer)
  555.                        new-term
  556.                        (KB-copy-aux subnode))))))))))
  557.       (if recursive-p
  558.       (KB-copy-aux term)
  559.     (%COPY-STRUCTURE term)))))
  560.  
  561. #||
  562. ;; test
  563. (setq $a (eval (READ-PARSER "walk(agt : John ) ")))
  564. (setq $aa (KB-copy $a))
  565. ;;
  566. (car (KB-tree-attributes (type-of $a)))
  567. ;; (ATOMIC-WFF--PREDICATE ATOMIC-WFF--ROLE-ARGUMENT-PAIRS)
  568. (eq (ATOMIC-WFF--PREDICATE $a) (ATOMIC-WFF--PREDICATE $aa)) ; NIL
  569. (equal (ATOMIC-WFF--PREDICATE $a) (ATOMIC-WFF--PREDICATE $aa)) ; Nil
  570. (kb-equal (ATOMIC-WFF--PREDICATE $a)  (ATOMIC-WFF--PREDICATE $aa)) ; T
  571. ;; note: equalp does recursive descent on structures
  572. (equalp (ATOMIC-WFF--PREDICATE $a) (ATOMIC-WFF--PREDICATE $aa))    ; T
  573.  
  574. (setq $b (eval (READ-PARSER "and{walk(agent: John) talk(agent: John)}")))
  575. (type-of $b)
  576. (car (KB-tree-attributes (type-of $b)))
  577. (setq $bb  (KB-copy $b))
  578.  
  579. ||#
  580.  
  581. ;----------------------------------------------------------------------------;
  582. ; KB-equal
  583. ;----------
  584. ; compares 2 objects of the KB-domain for equality. (something like term-equal?)
  585. ;  considers only tree-attributes as relevant
  586. ;  This is easier to extend for set-valued slots:
  587.  
  588. (defun KB-equalp (a b)
  589.   (declare (inline KB-TREE-ATTRIBUTES))
  590.   (check-type a KB-domain)
  591.   (check-type b KB-domain)
  592.   ;; ignores implementation of constants
  593.   (macrolet ((readers (x) `(the list (car (the cons ,x)))))
  594.     (labels ((KB-equal-aux (a b)
  595.            (let ((a-typ (type-of a)) (b-typ (type-of b)))
  596.          (unless (equal a-typ b-typ) (return-from KB-equal-aux 'Nil))
  597.          (let ((ta (KB-tree-attributes a-typ)))
  598.            (or
  599.             (null ta)
  600.             (dolist (reader (readers ta) t)
  601.               (declare (symbol reader))
  602.               (let* ((reader-fn (symbol-function reader))
  603.                  (a-subnode (funcall reader-fn a))
  604.                  (b-subnode (funcall reader-fn b)))
  605.             (unless (eq a-subnode b-subnode)
  606.               (unless (equal (type-of a-subnode) (type-of b-subnode))
  607.                 (return-from KB-equal-aux 'Nil))
  608.               (cond
  609.                 ((CONSp a-subnode) ; value is a set or sequence
  610.                  (if (= (the fixnum (length (the list a-subnode)))
  611.                     (the fixnum (length (the list b-subnode))))
  612.                  (if (KB-set-valued-slot-p reader)
  613.                      ;; We have 2 sets to compare
  614.                      ;; resort to this to avoid consing, see
  615.                      ;; comment below:
  616.                      (unless
  617.                      (and (dolist (bb (the list b-subnode) t)
  618.                         (unless (dolist (aa (the list a-subnode))
  619.                               (when (KB-equal-aux aa bb)
  620.                                 (return t)))
  621.                           (return nil)))
  622.                           (dolist (aa (the list a-subnode) t)
  623.                         (unless (dolist (bb (the list b-subnode))
  624.                               (when (KB-equal-aux aa bb)
  625.                                 (return t)))
  626.                           (return nil))))
  627.                        (return-from KB-equal-aux 'Nil))
  628.                    ;; We have two sequences to compare
  629.                    ;; Their elements must be in KB-domain
  630.                    (do ((arest a-subnode (cdr arest))
  631.                     (brest b-subnode (cdr brest)))
  632.                        ((atom arest) (eq arest brest))
  633.                      (let ((aa (car (the cons arest)))
  634.                        (bb (car (the cons brest))))
  635.                        (unless (KB-equal-aux aa bb)
  636.                      (return-from KB-equal-aux 'Nil)))))
  637.                    (return-from KB-equal-aux 'Nil)))
  638.                 ((KB-domain-p a-subnode)
  639.                  (unless (KB-equal-aux a-subnode b-subnode)
  640.                    (return-from KB-equal-aux 'Nil)))
  641.                 ((symbolp a-subnode)
  642.                  (unless (string-equal (symbol-name a-subnode)
  643.                            (symbol-name b-subnode))
  644.                    (return-from KB-equal-aux 'Nil)))
  645.                 (T (unless (equal a-subnode b-subnode)
  646.                  (return-from KB-equal-aux 'Nil))))))))))))
  647.       (or (eq a b)
  648.       (KB-equal-aux a b)))))
  649.  
  650. #||
  651. (KB-equalp (read-nll "DESKTOP-OBJECT(NAME: 'Orders--STR')")
  652.         (read-nll "DESKTOP-OBJECT(NAME: Orders--STR)"))
  653. (KB-equalp (read-nll "WORK(agent:+{'ABRAMS','BROWNE'})")
  654.         (read-nll "WORK(agent:+{ABRAMS,BROWNE})"))
  655. (compile 'KB-equalp)
  656. ||#
  657. (defun KB-equal (a b &optional verbose)
  658.   (declare (inline KB-TREE-ATTRIBUTES))
  659.   (macrolet ((readers (x) `(the list (car (the cons ,x)))))
  660.     (labels
  661.       ((KB-equal-aux (a b)
  662.      (let ((a-typ (type-of a)) (b-typ (type-of b)))
  663.        ;; (break "~S:~s = ~S:~s" a a-typ b b-typ)
  664.        (unless (equal a-typ b-typ) (return-from KB-equal-aux 'Nil))
  665.        (if (typep a 'KB-domain)
  666.            (let ((ta (KB-tree-attributes a-typ)))
  667.          (or
  668.           (null ta)
  669.           (dolist (reader (readers ta) t)
  670.             (declare (symbol reader))
  671.             (let* ((reader-fn (symbol-function reader))
  672.                (a-subnode (funcall reader-fn a))
  673.                (b-subnode (funcall reader-fn b)))
  674.               (when verbose
  675.             (format t "~% KB-compare ~S:~S ~%           = ~S:~S"
  676.                 a-subnode (type-of a-subnode)
  677.                 b-subnode (type-of b-subnode)))
  678.               (unless (eq a-subnode b-subnode)
  679.             (unless (equal (type-of a-subnode) (type-of b-subnode))
  680.               (return-from KB-equal-aux 'Nil))
  681.             (cond
  682.               ((CONSp a-subnode) ; value is a set or sequence
  683.                (if (= (the fixnum (length (the list a-subnode)))
  684.                   (the fixnum (length (the list b-subnode))))
  685.                    (if (KB-set-valued-slot-p reader)
  686.                    ;; We have 2 sets to compare
  687.                    ;; resort to this to avoid consing, see
  688.                    ;; comment below:
  689.                    (unless
  690.                        (and (dolist (bb (the list b-subnode) t)
  691.                           (unless (dolist (aa (the list a-subnode))
  692.                             (when (KB-equal-aux aa bb)
  693.                               (return t)))
  694.                         (return nil)))
  695.                         (dolist (aa (the list a-subnode) t)
  696.                           (unless (dolist (bb (the list b-subnode))
  697.                             (when (KB-equal-aux aa bb)
  698.                               (return t)))
  699.                         (return nil))))
  700.                      (return-from KB-equal-aux 'Nil))
  701.                  ;; We have two sequences to compare
  702.                  ;; Their elements must be in KB-domain
  703.                  (do ((arest a-subnode (cdr arest))
  704.                       (brest b-subnode (cdr brest)))
  705.                      ((atom arest) (eq arest brest))
  706.                    (let ((aa (car (the cons arest)))
  707.                      (bb (car (the cons brest))))
  708.                      (or (equal aa bb)
  709.                      (KB-equal-aux aa bb)
  710.                      (return-from KB-equal-aux 'Nil)))))
  711.                  (return-from KB-equal-aux 'Nil)))
  712.               ((KB-domain-p a-subnode)
  713.                (unless (KB-equal-aux a-subnode b-subnode)
  714.                  (return-from KB-equal-aux 'Nil)))
  715.               ((symbolp a-subnode)
  716.                (unless (string= (symbol-name a-subnode)
  717.                         (symbol-name b-subnode))
  718.                  (return-from KB-equal-aux 'Nil)))
  719.               (T (unless (equal a-subnode b-subnode)
  720.                    (return-from KB-equal-aux 'Nil)))))))))
  721.          (equal a b)))))
  722.       (or (eq a b)
  723.       (KB-equal-aux a b)))))
  724.  
  725. #|| test
  726. (KB-equal (make-Placeholder-Var :-Name 'u486)
  727.       (make-Placeholder-Var :-Name 'subject-nl-semantics))
  728. ||#
  729.  
  730. ;; the following is useful for testing
  731. (defun KB-compare (a b &optional verbose)
  732.   (check-type a KB-domain)
  733.   (check-type b KB-domain)
  734.   (KB-equal a b verbose))
  735.  
  736. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  737. ;;                       tree-attributes for kb-sequence
  738. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  739. (def-tree-attributes kb-sequence
  740.     kb-sequence-first kb-sequence-rest)
  741.  
  742. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  743. ;;; Generate (define-tree-attributes ..) for zebu
  744. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  745. ; Das nachfolgende kannst Du zur Generierung der Tree-Attributes
  746. ; verwenden. Prepare-Tree-Attributes kann auch zur Laufzeit die
  747. ; Attribute eintragen; wenn Du die Definitionen ins Domainfile
  748. ; uebernimmst, muesste Zebu define-tree-attributes immer kennen
  749. ; (zebu-kernel?).
  750.  
  751. ;; diese hashtable ist fuer zebra wiederverwenbar (der gruene punkt)
  752.  
  753. (defparameter *local-accessor-hashtable* (make-hash-table :test #'equal))
  754.  
  755. (defun labelnode2accessor (label topnode)
  756.   "Translates a label symbol and its topnode
  757.    into a structure accessor (-predicate atomic-wff -> at-wff--pred)"
  758.   (let* ((key (cons label topnode))
  759.          (constr (gethash key *local-accessor-hashtable*)))
  760.     (if constr
  761.     constr
  762.       (setf (gethash key *local-accessor-hashtable*)
  763.         (intern (concatenate 'string 
  764.                  (symbol-name topnode) "-"
  765.                  (symbol-name label)))))))
  766.  
  767. (defun prepare-tree-attributes (type &optional (output-only nil) (stream T))
  768.   "sets kb-tree-attributes of type and all of its subtypes"
  769.   (let ((slots (kb-slots type))
  770.         (slot-funs nil))
  771.     (dolist (item slots)
  772.       (if (symbolp item)
  773.           (push (labelnode2accessor item type) slot-funs)
  774.         ;; else
  775.         (push (labelnode2accessor (first item) type) slot-funs)))
  776.     (when slot-funs
  777.       (setq slot-funs (nreverse slot-funs))
  778.       (if output-only
  779.           (format stream "~S~%~%" 
  780.                   `(define-tree-attributes ',type '(,@slot-funs)))
  781.         ;; else
  782.         (define-tree-attributes type slot-funs)))
  783.     (dolist (item (kb-subtypes type))
  784.       (prepare-tree-attributes item output-only stream))))
  785.  
  786. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  787. ;;                     End of zebu-tree-attributes.lisp
  788. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  789.